package com.ygqh.baby.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.exception.WeixinPayException;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.payment.mch.PrePay;
import com.foxinmy.weixin4j.payment.mch.RefundResult;
import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.type.IdType;
import com.foxinmy.weixin4j.type.SignType;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.XmlStream;
import com.ygqh.baby.ao.AppType;
import com.ygqh.baby.ao.PayType;
import com.ygqh.baby.exception.YgException;
import com.ygqh.baby.po.YgPlatform;
import com.ygqh.baby.service.FileService;
import com.ygqh.baby.service.YgPayService;
import com.ygqh.baby.service.YgPlatformService;
import com.ygqh.baby.service.YgUserService;
import com.ygqh.baby.service.pay.UnifiedOrderResult;
import com.ygqh.baby.service.pay.app.weixin.WxAppUtils;
import com.ygqh.baby.service.wechat.WxConfig;
import com.ygqh.baby.service.wechat.api.YgPay3Api;
import com.ygqh.baby.service.wechat.model.WxPayAccount;
import com.ygqh.baby.service.wechat.notify.YgMchPayPackage;
import com.ygqh.baby.utils.ExceptionUtil;

@Service
public class YgPayServiceImpl implements YgPayService {

	Logger logger = Logger.getLogger(this.getClass());
	@Autowired
	private YgPlatformService ygPlatformService;
	@Autowired
	private YgUserService ygUserService;
	@Autowired
	private FileService fileService;

	@Override
	public UnifiedOrderResult unifiedOrder(YgPlatform platform, AppType appType, PayType payType, String paymentCode, BigDecimal price, String ipAddr,
			String openId, String notifyUrl, String attach) {

		try {
			PayRequest payRequest = null;
			String platformName = null;
			String platformNo = null;
			String orderInfo = null;
			if (PayType.Alipay.equals(payType)) {

			} else {
				if (platform != null) {
					platformName = platform.getName();
					platformNo = platform.getPlatformNo();
				}
				payRequest = wxUnifiedOrder(platform, appType, openId, paymentCode, price, ipAddr, attach, notifyUrl);
			}

			UnifiedOrderResult res = new UnifiedOrderResult(payType, platformNo, platformName);
			res.setPayRequest(payRequest);
			res.setOrderInfo(orderInfo);
			return res;
		} catch (Exception e) {
			logger.equals("统一下单失败；paymentCode = " + paymentCode + ";" + ExceptionUtil.getExceptionMsg(e));
			e.printStackTrace();
			return UnifiedOrderResult.error("统一下单失败", e.getMessage());
		}

	}

	private PayRequest wxUnifiedOrder(YgPlatform platform, AppType appType, String openId, String paymentCode, BigDecimal price, String ipAddr, String attach,
			String notifyUrl) throws WeixinPayException {
		notifyUrl = StringUtil.isNotBlank(notifyUrl) ? notifyUrl : WxConfig.getWxorderpaynotifyurl();

		int totalFee = price.multiply(new BigDecimal(100)).intValue();

		// 获取微信支付配置对象
		WeixinPayAccount payAccount = this.getWxPayAccount(platform, appType);

		// 支付类型
		TradeType tradeType = this.getTradeType(appType);

		// 预支付参数对象
		YgMchPayPackage mchPayPackage = this.getMchPayPackage(payAccount, openId, paymentCode, totalFee, notifyUrl, ipAddr, tradeType, attach, null);

		// 调用api
		YgPay3Api payApi = new YgPay3Api(payAccount);
		PrePay prePay = payApi.createPrePay(mchPayPackage);
		if (payAccount instanceof WxPayAccount) {
			WxPayAccount account = (WxPayAccount) payAccount;
			prePay.setAppId(account.getSubId());
		}
		

		PayRequest payRequest = getPayRequest(prePay, appType, payAccount.getPaySignKey());
		return payRequest;

	}

	private PayRequest getPayRequest(PrePay prePay, AppType appType, String paySignKey) {
		String packageInfo = null;
		if (AppType.Android.equals(appType) || AppType.Ios.equals(appType)) {
			packageInfo = "Sign=WXPay";
		} else {
			packageInfo = "prepay_id=" + prePay.getPrepayId();

		}
		PayRequest payRequest = new PayRequest(prePay.getAppId(), packageInfo);
		payRequest.setPrepayId(prePay.getPrepayId());
		payRequest.setSignType(SignType.MD5);
		payRequest.setPaySign(DigestUtil.paysignMd5(payRequest, paySignKey));
		return payRequest;

	}

	private TradeType getTradeType(AppType appType) {
		if (AppType.WeChat.equals(appType) || AppType.Small.equals(appType)) {
			return TradeType.JSAPI;
		} else if (AppType.Ios.equals(appType) || AppType.Android.equals(appType)) {
			return TradeType.APP;
		}
		return TradeType.NATIVE;

	}

	private WeixinPayAccount getWxPayAccount(YgPlatform platform, AppType appType) {
		WeixinPayAccount weixinPayAccount = null;
		if (platform != null) {
			String providerAppId = "wx563327e8dd35e422";
			weixinPayAccount = new WxPayAccount(providerAppId, null, platform.getPaySignKey(), platform.getMchId(), platform.getAppId(),
					platform.getSubMchId());
			System.out.println(weixinPayAccount.getSubMchId());
		} else {
			if (AppType.WeChat.equals(appType)) {
				weixinPayAccount = WxConfig.getWxpayaccount();
			} else if (AppType.Small.equals(appType)) {
				weixinPayAccount = WxConfig.getSmallpayaccount();

			} else if (AppType.Android.equals(appType) || AppType.Ios.equals(appType)) {
				weixinPayAccount = WxAppUtils.wxAppPayAccount;
			}
		}
		return weixinPayAccount;

	}

	private YgMchPayPackage getMchPayPackage(WeixinPayAccount weixinAccount, String openId, String paymentCode, int totalFee, String notifyUrl,
			String ipAddress, TradeType tradeType, String attach, String goodsTag) {
		YgMchPayPackage payPackage = null;
		if (weixinAccount instanceof WxPayAccount) {
			payPackage = new YgMchPayPackage((WxPayAccount) weixinAccount, null, openId, "壹果订单", paymentCode, totalFee, notifyUrl, ipAddress, tradeType,
					attach);

		} else {
			payPackage = new YgMchPayPackage(weixinAccount, openId, "壹果订单", paymentCode, totalFee, notifyUrl, ipAddress, tradeType);
		}
		if (StringUtil.isNotBlank(attach)) {
			payPackage.setAttach(attach);
		}
		if (StringUtil.isNotBlank(goodsTag)) {
			payPackage.setGoodsTag(goodsTag);
		}
		return payPackage;
	}

	@Override
	public void refund(YgPlatform platform, AppType appType, PayType payType, String returnCode, String orderPayCode, BigDecimal refundPrice,
			BigDecimal orderPrice) {
		WeixinPayAccount weixinPayAccount = this.getWxPayAccount(platform, appType);
		String certUrl = getCertUrl(platform, appType);

		this.weiXinRefund(weixinPayAccount, certUrl, returnCode, refundPrice, orderPrice, orderPayCode);

	}

	private String getCertUrl(YgPlatform platform, AppType appType) {
		String certUrl = "";
		if (platform != null) {
			certUrl=	WxConfig.getProvidercerturl();
		} else {
			if (AppType.WeChat.equals(appType)) {
				certUrl = WxConfig.getWxcerturl();
			} else if (AppType.Small.equals(appType)) {
				certUrl = WxConfig.getSmallcerturl();

			} else if (AppType.Android.equals(appType) || AppType.Ios.equals(appType)) {
				certUrl = WxAppUtils.wxAppCertUrl;
			}
		}
		return certUrl;

	}

	private RefundResult weiXinRefund(WeixinPayAccount weixinPayAccount, String certUrl, String returnCode, BigDecimal refundPrice, BigDecimal orderPrice,
			String orderPayCode) throws YgException {

		RefundResult result = null;
		try {
			InputStream inputStream = fileService.downloadIOFromOss(certUrl);

			YgPay3Api pay3Api = new YgPay3Api(weixinPayAccount);
			IdQuery idQuery = new IdQuery(orderPayCode, IdType.TRADENO);
			String res = pay3Api.refundApply(inputStream, idQuery, returnCode, orderPrice.doubleValue(), refundPrice.doubleValue(), CurrencyType.CNY,
					weixinPayAccount.getMchId());
			System.out.println(weixinPayAccount.toString());
			System.err.println(res);

			@SuppressWarnings("unchecked")
			Class<RefundResult> clazz = (Class<RefundResult>) new TypeReference<RefundResult>() {
			}.getType();
			XmlStream.fromXML(res, clazz);
		} catch (Exception e) {
			YgException exception = null;
			e.printStackTrace();
			if (e instanceof WeixinException) {
				exception = new YgException(((WeixinException) e).getErrorCode(), ((WeixinException) e).getErrorMsg());
				System.out.println(exception.getMessage());
			} else if (e instanceof IOException) {
				exception = new YgException("读取证书失败", e.toString());
			} else {
				exception = new YgException(e.getMessage());
			}
			throw exception;
		}
		return result;

	}
}
